package com.wlc.service.impl;

import com.wlc.mapper.LeaveMapper;
import com.wlc.pojo.LeaveApplication;
import com.wlc.pojo.PageResult;
import com.wlc.service.LeaveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class LeaveServiceImpl implements LeaveService {

    @Autowired
    private LeaveMapper leaveMapper;

    @Override
    public PageResult<LeaveApplication> findLeaveList(Long applicantId, Integer leaveType,
                                                      Integer status, String startDate,
                                                      String endDate, Integer page, Integer size) {
        log.info("查询请假列表: applicantId={}, leaveType={}, status={}, startDate={}, endDate={}, page={}, size={}",
                applicantId, leaveType, status, startDate, endDate, page, size);

        // 参数校验和默认值
        if (page == null || page < 1) page = 1;
        if (size == null || size < 1) size = 10;
        if (size > 100) size = 100;

        // 查询总数
        Long total = leaveMapper.selectLeaveCount(applicantId, leaveType, status, startDate, endDate);

        // 查询分页数据
        List<LeaveApplication> leaves = leaveMapper.selectLeaveList(applicantId, leaveType, status, startDate, endDate, (page - 1) * size, size);

        return new PageResult<>(total, leaves);
    }

    @Override
    public LeaveApplication findById(Long id) {
        log.info("根据ID查询请假: {}", id);
        LeaveApplication leave = leaveMapper.selectById(id);
        if (leave == null) {
            throw new RuntimeException("请假不存在");
        }
        return leave;
    }

    @Override
    @Transactional
    public void save(LeaveApplication leaveApplication) {
        log.info("新增请假: 申请人={}", leaveApplication.getApplicantName());

        // 参数校验
        validateLeaveApplication(leaveApplication);

        // 计算请假时长
        calculateDuration(leaveApplication);

        // 设置默认值
        leaveApplication.setStatus(0); // 待审批
        leaveApplication.setCreateTime(LocalDateTime.now());
        leaveApplication.setUpdateTime(LocalDateTime.now());

        // 设置请假类型名称
        leaveApplication.setLeaveTypeName(getLeaveTypeName(leaveApplication.getLeaveType()));

        int result = leaveMapper.insert(leaveApplication);
        if (result <= 0) {
            throw new RuntimeException("新增请假失败");
        }

        log.info("新增请假成功: ID={}", leaveApplication.getId());
    }

    @Override
    @Transactional
    public void update(LeaveApplication leaveApplication) {
        log.info("更新请假: {}", leaveApplication.getId());

        LeaveApplication existingLeave = leaveMapper.selectById(leaveApplication.getId());
        if (existingLeave == null) {
            throw new RuntimeException("请假不存在");
        }

        // 只有待审批状态的请假可以编辑
        if (existingLeave.getStatus() != 0) {
            throw new RuntimeException("只有待审批状态的请假可以编辑");
        }

        // 参数校验
        validateLeaveApplication(leaveApplication);

        // 重新计算请假时长
        calculateDuration(leaveApplication);

        // 设置请假类型名称
        if (leaveApplication.getLeaveType() != null) {
            leaveApplication.setLeaveTypeName(getLeaveTypeName(leaveApplication.getLeaveType()));
        }

        leaveApplication.setUpdateTime(LocalDateTime.now());
        int result = leaveMapper.update(leaveApplication);
        if (result <= 0) {
            throw new RuntimeException("更新请假失败");
        }

        log.info("更新请假成功: {}", leaveApplication.getId());
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        log.info("删除请假: {}", id);

        LeaveApplication leave = leaveMapper.selectById(id);
        if (leave == null) {
            throw new RuntimeException("请假不存在");
        }

        // 只能删除待审批或已撤销的请假
        if (leave.getStatus() != 0 && leave.getStatus() != 3) {
            throw new RuntimeException("只能删除待审批或已撤销的请假");
        }

        int result = leaveMapper.deleteById(id);
        if (result <= 0) {
            throw new RuntimeException("删除请假失败");
        }

        log.info("删除请假成功: {}", id);
    }

    @Override
    @Transactional
    public void cancelLeave(Long id, Long applicantId) {
        log.info("撤销请假: id={}, applicantId={}", id, applicantId);

        LeaveApplication leave = leaveMapper.selectById(id);
        if (leave == null) {
            throw new RuntimeException("请假不存在");
        }

        // 只能撤销自己的请假
        if (!leave.getApplicantId().equals(applicantId)) {
            throw new RuntimeException("只能撤销自己的请假");
        }

        // 只能撤销待审批状态的请假
        if (leave.getStatus() != 0) {
            throw new RuntimeException("只能撤销待审批状态的请假");
        }

        // 更新状态为已撤销
        leave.setStatus(3); // 已撤销
        leave.setUpdateTime(LocalDateTime.now());
        int result = leaveMapper.update(leave);
        if (result <= 0) {
            throw new RuntimeException("撤销请假失败");
        }

        log.info("撤销请假成功: {}", id);
    }

    @Override
    public List<Map<String, Object>> getLeaveTypes() {
        log.info("获取请假类型列表");

        List<Map<String, Object>> types = new ArrayList<>();

        Map<String, Object> type1 = new HashMap<>();
        type1.put("value", 1);
        type1.put("label", "年假");
        types.add(type1);

        Map<String, Object> type2 = new HashMap<>();
        type2.put("value", 2);
        type2.put("label", "病假");
        types.add(type2);

        Map<String, Object> type3 = new HashMap<>();
        type3.put("value", 3);
        type3.put("label", "事假");
        types.add(type3);

        Map<String, Object> type4 = new HashMap<>();
        type4.put("value", 4);
        type4.put("label", "婚假");
        types.add(type4);

        Map<String, Object> type5 = new HashMap<>();
        type5.put("value", 5);
        type5.put("label", "产假");
        types.add(type5);

        Map<String, Object> type6 = new HashMap<>();
        type6.put("value", 6);
        type6.put("label", "丧假");
        types.add(type6);

        Map<String, Object> type7 = new HashMap<>();
        type7.put("value", 7);
        type7.put("label", "调休");
        types.add(type7);

        return types;
    }

    @Override
    @Transactional
    public void approveLeave(Long id, Integer status, String approveRemark, Long approverId, String approverName) {
        log.info("审批请假: id={}, status={}, approverId={}", id, status, approverId);

        // 校验请假是否存在
        LeaveApplication leave = leaveMapper.selectById(id);
        if (leave == null) {
            throw new RuntimeException("请假不存在");
        }

        // 校验状态
        if (leave.getStatus() != 0) {
            throw new RuntimeException("该请假已审批，无法重复审批");
        }

        // 校验审批状态值
        if (status != 1 && status != 2) {
            throw new RuntimeException("审批状态值不合法");
        }

        // 更新审批信息
        leave.setStatus(status);
        leave.setApproveRemark(approveRemark);
        leave.setApproverId(approverId);
        leave.setApproverName(approverName);
        leave.setApproveTime(LocalDateTime.now());
        leave.setUpdateTime(LocalDateTime.now());

        int result = leaveMapper.update(leave);
        if (result <= 0) {
            throw new RuntimeException("审批失败");
        }

        log.info("审批请假成功: id={}, status={}", id, status);
    }

    /**
     * 根据请假类型代码获取类型名称
     */
    private String getLeaveTypeName(Integer leaveType) {
        return switch (leaveType) {
            case 1 -> "年假";
            case 2 -> "病假";
            case 3 -> "事假";
            case 4 -> "婚假";
            case 5 -> "产假";
            case 6 -> "丧假";
            case 7 -> "调休";
            default -> "其他";
        };
    }

    /**
     * 验证请假申请参数
     */
    private void validateLeaveApplication(LeaveApplication leaveApplication) {
        if (leaveApplication.getLeaveType() == null) {
            throw new RuntimeException("请假类型不能为空");
        }
        if (leaveApplication.getStartTime() == null) {
            throw new RuntimeException("开始时间不能为空");
        }
        if (leaveApplication.getEndTime() == null) {
            throw new RuntimeException("结束时间不能为空");
        }
        if (leaveApplication.getStartTime().isAfter(leaveApplication.getEndTime())) {
            throw new RuntimeException("开始时间不能晚于结束时间");
        }
        if (leaveApplication.getReason() == null || leaveApplication.getReason().trim().isEmpty()) {
            throw new RuntimeException("请假事由不能为空");
        }
        if (leaveApplication.getReason().length() > 500) {
            throw new RuntimeException("请假事由长度不能超过500个字符");
        }
    }

    /**
     * 计算请假时长（天数）- 使用 Duration 替代 ChronoUnit
     */
    private void calculateDuration(LeaveApplication leaveApplication) {
        if (leaveApplication.getStartTime() != null && leaveApplication.getEndTime() != null) {
            Duration duration = Duration.between(leaveApplication.getStartTime(), leaveApplication.getEndTime());
            long hours = duration.toHours();
            double days = hours / 24.0;
            // 保留两位小数
            leaveApplication.setDuration(Math.round(days * 100.0) / 100.0);

            log.debug("计算请假时长: 从 {} 到 {}, 共计 {} 小时, {} 天",
                    leaveApplication.getStartTime(),
                    leaveApplication.getEndTime(),
                    hours,
                    leaveApplication.getDuration());
        }
    }

    /**
     * 获取请假统计信息
     */
    public Map<String, Object> getLeaveStatistics(Long applicantId, String startDate, String endDate) {
        log.info("获取请假统计: applicantId={}, startDate={}, endDate={}", applicantId, startDate, endDate);

        Map<String, Object> statistics = new HashMap<>();

        // 待审批数量
        Long pendingCount = leaveMapper.selectLeaveCount(applicantId, null, 0, startDate, endDate);
        statistics.put("pendingCount", pendingCount != null ? pendingCount : 0);

        // 已通过数量
        Long approvedCount = leaveMapper.selectLeaveCount(applicantId, null, 1, startDate, endDate);
        statistics.put("approvedCount", approvedCount != null ? approvedCount : 0);

        // 已拒绝数量
        Long rejectedCount = leaveMapper.selectLeaveCount(applicantId, null, 2, startDate, endDate);
        statistics.put("rejectedCount", rejectedCount != null ? rejectedCount : 0);

        // 已撤销数量
        Long canceledCount = leaveMapper.selectLeaveCount(applicantId, null, 3, startDate, endDate);
        statistics.put("canceledCount", canceledCount != null ? canceledCount : 0);

        return statistics;
    }
}